#============================================================
#    Executor
#============================================================
# - datetime: 2022-12-21 11:16:44
#============================================================
## 功能执行器
class_name Executor



class _BaseTimer extends Timer:
	var _finished_callable := Callable()
	
	func _add_to_scene(to: Node = null):
		if to == null:
			to = Engine.get_main_loop().current_scene
		to.add_child(self)
	
	func _finished(params: Array = []):
		if not _finished_callable.is_null():
			_finished_callable.callv(params)
	
	func finished(callable: Callable):
		_finished_callable = callable
	
	func stop():
		super.stop()


#============================================================
#  执行对象
#============================================================
class _ExecutorObject extends _BaseTimer:
	
	var _finish : bool = false
	var _callable: Callable
	var _condition := Callable()
	
	func _init(callable: Callable):
		_callable = callable
		self.timeout.connect(_finished, Object.CONNECT_ONE_SHOT)
	
	func _enter_tree():
		self.set_process(process_callback == Timer.TIMER_PROCESS_IDLE)
		self.set_physics_process(process_callback == Timer.TIMER_PROCESS_PHYSICS)
		self.start()
	
	func _process(delta):
		if not _condition.is_null() and _condition.call():
			_finished()
		else:
			_callable.call()
	
	func _physics_process(delta):
		if not _condition.is_null() and _condition.call():
			_finished()
		else:
			_callable.call()
	
	func _finished(params = []):
		super._finished(params)
		_finish = true
		self.queue_free()
		set_physics_process(false)
		set_process(false)
	
	func finished(callable: Callable) -> _ExecutorObject:
		super.finished(callable)
		return self
	
	## 设置执行时中断并结束的条件
	func set_finish_condition(condition: Callable) -> _ExecutorObject:
		_condition = condition
		return self


#============================================================
#  间隔执行计时器
#============================================================
class _IntermittentTimer extends _BaseTimer:
	
	var _amount_left : int = 0
	var _max_count: int = 0
	
	## 剩余数量
	func get_amount_left() -> int:
		return _amount_left
	
	## 获取最大次数
	func get_max_amount() -> int:
		return _max_count
	
	func _init(callable: Callable, max_count: int) -> void:
		assert(max_count > 0, "最大执行次数必须超过0！")
		_max_count = max_count
		_amount_left = max_count
		self.timeout.connect(func():
			callable.call()
			if _amount_left == 0:
				self.stop()
				_finished()
				self.queue_free()
			_amount_left -= 1
		)
	
	## 执行结束调用这个回调
	func finished(callable: Callable) -> _IntermittentTimer:
		_finished_callable = callable
		return self


#============================================================
#  列表时间间隔执行计时器
#============================================================
class _IntermittentListTimer extends _BaseTimer:
	var _list = []
	var _callable : Callable = Callable()
	var _executed_callable: Callable = Callable()
	var _time : float
	
	func _init(list: PackedFloat64Array, callable: Callable):
		_list = list
		_list.reverse()
		_callable = callable
		self.timeout.connect(func():
			if not _callable.is_null():
				_callable.call()
			if not _executed_callable.is_null():
				_executed_callable.call(_time)
			self._next()
		)
	
	func _enter_tree():
		_next()
	
	func _next() -> void:
		if _list.size() == 0:
			_finished()
			self.queue_free()
			return
		
		_time = _list.pop_back()
		if _time == 0:
			self.timeout.emit()
		else:
			self.start(_time)
	
	# 每个时间执行结束之后，调用这个方法，这个方法需要有一个 [float] 参数接收这次结束的时间的值
	func executed(callable: Callable) -> _IntermittentListTimer:
		_executed_callable = callable
		return self
	
	## 完全执行结束调用这个回调
	func finished(callable: Callable) -> _IntermittentListTimer:
		super.finished(callable)
		return self
	


#============================================================
#  自定义
#============================================================
## 执行一个片段线程
##[br]
##[br][code]duration[/code]  持续时间
##[br][code]callable[/code]  每帧执行的回调方法
##[br][code]params[/code]  传入方法的参数值
##[br][code]process_callback[/code]  线程类型：0 physics 线程 [member Timer.TIMER_PROCESS_PHYSICS]
##，1 普通 process 线程 [member Timer.TIMER_PROCESS_IDLE]
##[br]
##[br][code]return[/code]  返回执行对象
static func execute_fragment_process(
	duration: float,
	callable: Callable, 
	process_callback : int = Timer.TIMER_PROCESS_PHYSICS
) -> _ExecutorObject:
	var timer := _ExecutorObject.new(callable)
	timer.process_callback = process_callback
	timer.wait_time = duration
	timer._add_to_scene()
	return timer


##  间歇性执行
##[br]
##[br][code]interval[/code]  间隔执行时间
##[br][code]count[/code]  执行次数
##[br][code]callable[/code]  回调方法
##[br]
##[br][code]return[/code]  返回执行的计时器
static func intermittent_execute(interval: float, count: int, callable: Callable) -> _IntermittentTimer:
	var timer = _IntermittentTimer.new(callable, count)
	timer.wait_time = interval
	timer.one_shot = false
	timer.autostart = true
	timer._add_to_scene()
	return timer


##  根据传入的时间列表间歇执行
##[br]
##[br][code]interval_list[/code]  时间列表
##[br][code]callable[/code]  回调方法
##[br][code]return[/code]  返回间歇执行计时器对象
static func intermittent_execute_by_list(
	interval_list: PackedFloat64Array, 
	callable: Callable = Callable()
) -> _IntermittentListTimer:
	var timer =  _IntermittentListTimer.new(interval_list, callable)
	timer.one_shot = true
	timer.autostart = false
	timer._add_to_scene()
	return timer

